package com.dongdong.android.framework.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Handler;
import android.os.HandlerThread;

import com.dongdong.android.framework.base.BaseApplication;
import com.dongdong.android.framework.db.base.DbBaseEntity;
import com.dongdong.android.framework.utils.LogUtil;
import com.j256.ormlite.dao.Dao;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * 数据库管理类,提供数据库的增删查改接口,统一处理数据的读写分离
 * Created by dongdong on 2018/3/27.
 */

public class DbManager {
    public static final String TAG = "DbManager";

    public static final int DB_CODE_FAIL = -1;

    private static DbManager instance;


    private DbManager() {
    }

    public static DbManager getInstance() {
        if (null == instance) {
            synchronized (DbManager.class) {
                if (null == instance) {
                    instance = new DbManager();
                }
            }
        }
        return instance;
    }

    /**
     * application 应该在application 启动的时候初始化数据库,或者在第一次操作数据的时候初始化
     *
     * @param dbName    db name
     * @param dbVersion version
     * @param tables    tables
     */
    public static void initDB(String dbName, int dbVersion, List<Class> tables) {
        DbHelper.initDB(dbName, dbVersion, tables);
        DbHelper.getInstance();

    }

    /**
     * 保存或者更新实体 异步操作
     * 数据通过本地广播返回,监听实体对应表的 ACTION_MODEL_UPDATE 通知
     */
    public int saveOrUpdate(DbBaseEntity entity) {
        Class clz = entity.getClass();
        try {
            entity.encodeBlobData();
            final Dao dao = getDao(clz);
            Dao.CreateOrUpdateStatus status = dao.createOrUpdate(entity);
            int result = 0;
            if (status.isCreated()) {
                result = 1;
            } else if (status.isUpdated()) {
                result = 2;
            }
            return result;
        } catch (SQLException e) {
            e.printStackTrace();
            LogUtil.e(e.toString());
            return 0;
        }
    }

    /**
     * 保存或者更新实体
     * 数据通过本地广播返回,监听实体对应表的 ACTION_MODEL_UPDATE 通知
     */
    public boolean saveOrUpdate(final List<? extends DbBaseEntity> entities) {

        if (null == entities || entities.size() == 0) {
            return true;
        }

        for (DbBaseEntity entity : entities) {
            entity.encodeBlobData();
        }

        try {
            DbBaseEntity entity = entities.get(0);
            Class clz = entity.getClass();
            final Dao dao = getDao(clz);
            dao.callBatchTasks(new Callable<Void>() {

                @Override
                public Void call() throws Exception {

                    for (DbBaseEntity entity : entities) {
                        dao.createOrUpdate(entity);
                    }
                    return null;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.e(TAG, e);
            return false;
        }

        return true;
    }


    /**
     * 删除实体
     *
     * @param entity 实体集合
     */
    public int delete(DbBaseEntity entity) {
        Class clz = entity.getClass();
        try {
            final Dao dao = getDao(clz);
            return dao.delete(entity);
        } catch (SQLException e) {
            e.printStackTrace();
            LogUtil.e(e.toString());
            return DB_CODE_FAIL;
        }
    }

    /**
     * 删除实体
     */
    public int deleteById(Class clz, Object id) {
        try {
            final Dao dao = getDao(clz);
            return dao.deleteById(id);
        } catch (SQLException e) {
            e.printStackTrace();
            LogUtil.e(e.toString());
            return DB_CODE_FAIL;
        }
    }

    /**
     * 删除实体
     *
     * @param entities 实体集合
     */
    public int delete(final List<? extends DbBaseEntity> entities) {

        try {
            DbBaseEntity entity = entities.get(0);
            Class clz = entity.getClass();
            final Dao dao = getDao(clz);
            dao.callBatchTasks(new Callable<Void>() {

                @Override
                public Void call() throws Exception {

                    for (DbBaseEntity entity : entities) {
                        dao.delete(entity);
                    }
                    return null;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            return DB_CODE_FAIL;
        }

        return 0;
    }


    /**
     * 根据对象的ID字段条件查询
     *
     * @param entityType 实体类型
     * @param idValue    实体对象
     * @return 返回实体对象
     */
    public <T extends DbBaseEntity> T queryForId(final Class<T> entityType, Object idValue) {
        try {
            Class clz = entityType;
            T entity = (T) DbHelper.getInstance().getDao(clz).queryForId(idValue);
            return entity;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

//    /**
//     * 根据对象查询,查询ID字段
//     *
//     * @param entityType 实体类型
//     * @param idValue    实体对象
//     * @return 返回实体对象
//     */
//    public <T extends DbBaseEntity> T queryForSameId(final Class<T> entityType, T idValue) {
//        try {
//            Class clz = entityType;
//            T entity = (T) HTDBHelper.getHelper().getDao(clz).queryForSameId(idValue);
//            return entity;
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    /**
     * 查询指定字段value等于查询值的行： where fieldName ＝ value
     *
     * @param entityType
     * @param fieldName
     * @param value
     * @param <T>
     * @return
     */
    public <T extends DbBaseEntity> List<T> queryForEq(final Class<T> entityType, String fieldName, Object value) {

        Map<String, Object> map = new HashMap<>();
        map.put(fieldName, value);
        return queryForFieldValues(entityType, map);
    }


    /**
     * 查询指定字段value等于查询值的行： where fieldName ＝ value
     *
     * @param entityType
     * @param <T>
     * @return
     */
    public <T extends DbBaseEntity> List<T> queryForAll(final Class<T> entityType) {
        try {
            Class clz = entityType;
            List<T> entities = DbHelper.getInstance().getDao(clz).queryForAll();
            return entities;
        } catch (SQLException e) {
            e.printStackTrace();
            LogUtil.e(TAG, e);
        }
        return null;
    }

    /**
     * 根据条件集查询
     *
     * @param entityType 实体类型
     * @param <T>        实体泛型
     * @return 同步查询 返回结果集 异步查询返回空,应该监听ACTION_MODEL_FIND回调
     */
    public <T extends DbBaseEntity> List<T> queryForFieldValues(final Class<T> entityType,
                                                                Map<String, Object> fieldValues) {

        if (null == fieldValues) {
            fieldValues = new HashMap<>();
        }
        try {
            Class clz = entityType;
            List<T> entities = (List<T>) DbHelper.getInstance().getDao(clz).queryForFieldValues(fieldValues);
            return entities;
        } catch (SQLException e) {
            e.printStackTrace();
            LogUtil.d(TAG, e);
        }
        return null;
    }

    /**
     * 有些操作可能没法完全提供的,直接使用Dao查询,APP应该尽量少的使用,会对Dao产生耦合,对Dao的操作最好使用单独一层接口封装
     *
     * @param clazz
     * @param <D>
     * @param <T>
     * @return
     * @throws SQLException
     */
    public <D extends Dao<T, ?>, T> D getDao(Class<T> clazz) throws SQLException {
        try {
            return DbHelper.getInstance().getDao(clazz);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void close() {
        DbHelper.getInstance().close();
    }

}

